#pragma once

#include <iostream>
#include <vector>
#include <mutex>

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include "log.hpp"
#include "localmutex.hpp"
#include "inetaddr.hpp"

namespace Local_Routle
{
    class Routle
    {
    public:
        Routle()
        {
        }
        // 进入聊天室
        void Push(Local_Inetaddr::Inetaddr &input)
        {
            _allvec.emplace_back(input);
            Local_Log::LOG(Local_Log::LogLever::HELLO) << input.GetStrAddr();
        }
        // 离开聊天室
        void Pop(Local_Inetaddr::Inetaddr &input)
        {
            for (auto it = _allvec.begin(); it == _allvec.end(); ++it)
            {
                if ((*it) == input)
                {
                    _allvec.erase(it);
                    Local_Log::LOG(Local_Log::LogLever::BYBY) << input.GetStrAddr();
                    return;
                }
            }
        }
        // 用户是否存在
        bool IsMember(Local_Inetaddr::Inetaddr &input)
        {
            for (auto &it : _allvec)
            {
                if (it == input)
                {
                    return true;
                }
            }
            return false;
        }
        // 转发给所有成员
        void Forward(int sockfd, const std::string &str, Local_Inetaddr::Inetaddr &input)
        {
            Local_Mutex::LockGuard guard(&_mutex);
            if (!IsMember(input))
            {
                Local_Log::LOG(Local_Log::LogLever::LINFO) << "新增一个在线用户: " << input.GetStrAddr();
                Push(input);
            }
            // for (auto &it : _allvec)
            // {
            //     std::cout << it.GetIp() << std::endl;
            // }
            for (auto &it : _allvec)
            {
                // if (it != input)
                {
                    std::string send = input.GetStrAddr() + " # " + str;
                    ssize_t send_ret = sendto(sockfd, send.c_str(), send.size(), 0, (const struct sockaddr *)&(it.GetAddr()), sizeof(it.GetAddr()));
                    // Local_Log::LOG(Local_Log::LogLever::LINFO) << "send::" << it.GetIp() << str;
                    if (send_ret == -1)
                    {
                        Local_Log::LOG(Local_Log::LogLever::LINFO) << "sendto error";
                    }
                }
            }
            // 这个用户一定已经在线了
            if (str == "QUIT")
            {
                Local_Log::LOG(Local_Log::LogLever::LINFO) << "删除一个在线用户: " << input.GetStrAddr();
                Pop(input);
            }
        }

    private:
        std::vector<Local_Inetaddr::Inetaddr> _allvec;
        Local_Mutex::LocalMutex _mutex;
    };
}